#include "DockWidgetManager.h"
#include "DockTitleBarWidget.h"
#include "ui_DockWidgetManager.h"
#include "CameraPluginInterface.h"

#include <QDockWidget>
#include <QMdiArea>
#include <QDebug>
#include <QDialog>

/**
 * @brief DockWidgetManager构造函数
 * 
 * 初始化DockWidgetManager的实例，设置UI、窗口属性、创建dock widgets映射表、
 * 初始化dock标题和布局，并连接各种信号槽。
 * 
 * @param parent 父窗口组件
 */
DockWidgetManager::DockWidgetManager(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::DockWidgetManager)
{
    // 设置UI
    ui->setupUi(this);

    // 初始化窗口属性
    setDockNestingEnabled(true);
    setContentsMargins(5, 0, 5, 5);
    
    // 将dock widgets添加到映射表中
    m_dockWidgetsMap.insert(DockWidgetType::DeviceControl, ui->deviceControlDock);
    m_dockWidgetsMap.insert(DockWidgetType::ImageDisplay, ui->imageDisplayDock);
    m_dockWidgetsMap.insert(DockWidgetType::ImageProcessing, ui->imageProcessingDock);
    m_dockWidgetsMap.insert(DockWidgetType::MeasurementResults, ui->measurementResultsDock);
    m_dockWidgetsMap.insert(DockWidgetType::MeasurementTools, ui->measurementToolsDock);
    m_dockWidgetsMap.insert(DockWidgetType::SoftwareLog, ui->softwareLogDock);
    m_dockWidgetsMap.insert(DockWidgetType::ImagePreview, ui->imagePreviewDock);
    
    // 初始化dock标题
    initDockTitle();

    //初始化布局
    initWorkSpace();
    // 连接菜单项的信号槽，用于控制dock的显示和隐藏
    connect(ui->action_DeviceControl, &QAction::triggered, this, [this](bool checked) {
        ui->deviceControlDock->setVisible(checked);
    });
    connect(ui->action_ImageProcessing, &QAction::triggered, this, [this](bool checked) {
        ui->imageProcessingDock->setVisible(checked);
    });
    connect(ui->action_MeasurementTools, &QAction::triggered, this, [this](bool checked) {
        ui->measurementToolsDock->setVisible(checked);
    });
    connect(ui->action_ImagePreview, &QAction::triggered, this, [this](bool checked) {
        ui->imagePreviewDock->setVisible(checked);
    });
    connect(ui->action_MeasurementResults, &QAction::triggered, this, [this](bool checked) {
        ui->measurementResultsDock->setVisible(checked);
    });
    connect(ui->action_SoftwareLog, &QAction::triggered, this, [this](bool checked) {
        ui->softwareLogDock->setVisible(checked);
    });

    ui->mdiArea_ImageDisplay->setViewMode(QMdiArea::TabbedView);
    // 连接QMdiArea的subWindowActivated信号到DockWidgetManager
    connect(ui->mdiArea_ImageDisplay, &QMdiArea::subWindowActivated, this, [this](QMdiSubWindow *activatedWindow) {
        if (activatedWindow) {
            // 查找被激活窗口对应的graphicsGuid
            for (auto it = m_GraphicsSubWindowMap.constBegin(); it != m_GraphicsSubWindowMap.constEnd(); ++it) {
                if (it.value() == activatedWindow) {
                    // 通知DockWidgetManager处理窗口切换
                    emit graphicsDisplayWidgetSwitched(it.key());
                    break;
                }
            }
        }
    });
}

/**
 * @brief DockWidgetManager析构函数
 * 
 * 清理DockWidgetManager占用的资源，包括释放UI对象和清空映射表。
 */
DockWidgetManager::~DockWidgetManager()
{
    // 清理资源
    delete ui;
    m_dockWidgetsMap.clear();
    // 清空图形子窗口映射表
    m_GraphicsSubWindowMap.clear();
}

/**
 * @brief 初始化工作区布局
 * 
 * 配置所有停靠窗口的初始位置、分割方式和大小比例，建立应用程序的基本布局结构。
 * 使用splitDockWidget函数将主窗口划分为多个区域，并使用resizeDocks设置各区域的初始大小。
 */
void DockWidgetManager::initWorkSpace()
{
    // 初始化工作区布局
    takeCentralWidget(); // 删除中央窗体
    setDockNestingEnabled(true); // 允许嵌套dock
    
    addDockWidget(Qt::LeftDockWidgetArea,ui->deviceControlDock);
    splitDockWidget(ui->deviceControlDock,ui->imageDisplayDock,Qt::Horizontal);
    splitDockWidget(ui->imageDisplayDock,ui->measurementResultsDock,Qt::Horizontal);
    splitDockWidget(ui->deviceControlDock,ui->imageProcessingDock,Qt::Vertical);
    splitDockWidget(ui->imageProcessingDock,ui->measurementToolsDock,Qt::Vertical);
    splitDockWidget(ui->imageDisplayDock,ui->imagePreviewDock,Qt::Vertical);
    splitDockWidget(ui->measurementResultsDock,ui->softwareLogDock,Qt::Vertical);

    resizeDocks(QList<QDockWidget*>()<<ui->deviceControlDock<<ui->imageProcessingDock<<ui->measurementToolsDock,
                      QList<int>()<<static_cast<int>(this->geometry().width()*0.4)<<static_cast<int>(this->geometry().width()*0.3)<<static_cast<int>(this->geometry().width()*0.3),Qt::Vertical);
    resizeDocks(QList<QDockWidget*>()<<ui->measurementResultsDock<<ui->softwareLogDock,
                      QList<int>()<<static_cast<int>(this->geometry().width()*0.4)<<static_cast<int>(this->geometry().width()*0.6),Qt::Vertical);
    resizeDocks({ui->imageDisplayDock,ui->imagePreviewDock},{static_cast<int>(this->geometry().height()-150),150},Qt::Vertical);
//    resizeDocks({ui->deviceControlDock,ui->imageDisplayDock,ui->measurementResultsDock},{300,static_cast<int>(this->geometry().width()-300-300),300},Qt::Horizontal);
}    

/**
 * @brief 初始化dock标题栏
 * 
 * 为所有停靠窗口设置自定义标题栏，添加标题显示和控制按钮。
 * 遍历m_dockWidgetsMap中的所有dock widget，为每个有效widget创建DockTitleBarWidget实例。
 */
void DockWidgetManager::initDockTitle()
{
    // 遍历所有dock widget并设置自定义标题栏
    for (auto it = m_dockWidgetsMap.constBegin(); it != m_dockWidgetsMap.constEnd(); ++it) {
        QDockWidget *dockWidget = it.value();
        if (dockWidget) {
            DockTitleBarWidget* pDockTitleBarWidget = new DockTitleBarWidget(dockWidget);
            pDockTitleBarWidget->setObjectName(QString("%1_TitleBar").arg(dockWidget->objectName()));
            pDockTitleBarWidget->setTitle(dockWidget->windowTitle());
            dockWidget->setTitleBarWidget(pDockTitleBarWidget);
        }
    }
}


/**
 * @brief 获取特定类型的dock widget
 * 
 * 根据传入的类型从m_dockWidgetsMap中查找并返回对应的QDockWidget指针。
 * 
 * @param type 要获取的停靠窗口类型
 * @return 对应的QDockWidget指针，如果类型无效或不存在则返回nullptr
 */
QDockWidget* DockWidgetManager::getDockWidget(DockWidgetType type) const
{
    if (m_dockWidgetsMap.contains(type)) {
        return m_dockWidgetsMap[type];
    }
    return nullptr;
}

/**
 * @brief 获取菜单栏
 * 
 * 返回主窗口的菜单栏指针，用于外部访问和操作菜单。
 * 
 * @return 主窗口的菜单栏指针
 */
QMenuBar* DockWidgetManager::menuBar() const
{
    return ui->menuBar;
}

/**
 * @brief 注册widget到指定的QDockWidget
 * 
 * 将给定的widget组件添加到指定类型的停靠窗口中。如果目标停靠窗口中已有widget，
 * 会先清理现有widget，然后将新widget添加进去。
 * 
 * @param type 目标停靠窗口类型
 * @param widget 要注册的窗口组件
 * @return 注册是否成功
 */
bool DockWidgetManager::registerWidgetToDock(DockWidgetType type, QWidget *widget)
{
    // 检查widget指针是否有效
    if (!widget) {
        return false;
    }

    // 从映射表中获取对应的QDockWidget
    QDockWidget *dockWidget = getDockWidget(type);
    if (!dockWidget) {
        qDebug() << "注册widget失败：DockWidgetManager中没有找到对应的QDockWidget";
        return false;
    }

    QString dockName;
    switch (type) {
    case DockWidgetType::DeviceControl:
        dockName = "DeviceControl";
        break;
    case DockWidgetType::ImageProcessing:
        dockName = "ImageProcessing";
        break;
    case DockWidgetType::MeasurementTools:
        dockName = "MeasurementTools";
        break;
    case DockWidgetType::MeasurementResults:
        dockName = "MeasurementResults";
        break;
    case DockWidgetType::SoftwareLog:
        dockName = "SoftwareLog";
        break;
    case DockWidgetType::ImagePreview:
        dockName = "ImagePreview";
        break;
    default:
        return false; // 无效的枚举类型
    }
    
    // 如果找到对应的QDockWidget
    if (dockWidget) {
        qDebug() << "找到对应的停靠窗口：" << dockName;
        // 获取现有的widget
        QWidget *existingWidget = dockWidget->widget();
        if (existingWidget) {
            // 尝试获取existingWidget的布局
            QLayout *layout = existingWidget->layout();
            if (layout) {
                // 确保布局中没有其他widget
                while (layout->count() > 0) {
                    QLayoutItem *item = layout->takeAt(0);
                    if (item->widget()) {
                        layout->removeItem(item);
                        item->widget()->setParent(nullptr);
                    }
                    delete item;
                }
                
                // 将新的widget添加到现有布局中
                layout->addWidget(widget);
                return true;
            }
        }
        
        // 如果没有现有widget或布局，才直接设置新的widget
        dockWidget->setWidget(widget);
        return true;
    }

    qDebug() << "注册widget失败：没有找到对应的QDockWidget";
    return false; // 没有找到对应的QDockWidget
}

/**
 * @brief 注册菜单项到主窗口（重载1）
 * 
 * 将菜单项或子菜单添加到菜单栏或指定的子菜单中。根据menuObject的实际类型，
 * 决定是添加新的顶层菜单还是添加菜单项到现有菜单。
 * 
 * @param menuIndex 目标菜单索引，-1表示添加到菜单栏末尾
 * @param menuObject 要添加的QMenu或QAction对象
 */
void DockWidgetManager::onRegisterMenuItem(int menuIndex, QObject *menuObject)
{
    if (!menuObject) {
        return;
    }

    // 获取菜单栏
    QMenuBar *menuBar = ui->menuBar;
    if (!menuBar) {
        qDebug() << "无法获取菜单栏";
        return;
    }

    // 尝试将QObject转换为QMenu
    QMenu *menu = qobject_cast<QMenu*>(menuObject);
    if (menu) {
        // 添加新菜单到菜单栏
        menuBar->addMenu(menu)->setParent(menuBar);
        return;
    }
    // 将QObject转换为QAction
    QAction *menuAction = qobject_cast<QAction*>(menuObject);
    if (menuAction) {
        if (menuIndex >= 0 && menuIndex < menuBar->actions().size()) {
            QMenu *targetMenu = menuBar->actions().at(menuIndex)->menu();
            if (targetMenu) {
                targetMenu->addAction(menuAction);
            }
        } else {
            // 如果索引无效或为-1，添加到菜单栏末尾
            menuBar->addAction(menuAction);
        }
    }
}

/**
 * @brief 注册菜单项到主窗口（重载2）
 * 
 * 根据索引路径在菜单层次结构中创建或查找菜单位置，并添加新的菜单项。
 * 菜单项点击时会显示指定的对话框。
 * 
 * @param indexs 菜单索引路径向量，每一层的索引值
 * @param title 菜单项显示的文本
 * @param pActionWidget 点击菜单项时显示的对话框
 */
void DockWidgetManager::onRegisterMenuItem(const QVector<int>& indexs, const QString& title, QDialog* pActionWidget)
{
    // 获取菜单栏
    QMenuBar* menuBar = ui->menuBar;
    if (!menuBar) {
        qWarning() << "无法获取菜单栏";
        return;
    }
    
    // 检查title是否为空
    if (title.isEmpty()) {
        qWarning() << "菜单项标题不能为空";
        return;
    }
    
    // 创建菜单项对应的QAction
    QAction* action = nullptr;
    // 根据indexs向量确定菜单项的添加位置
    if (indexs.isEmpty()) {
        // 如果indexs为空，直接添加到菜单栏最外层
        menuBar->addAction(action=new QAction(title,menuBar));
    } else {
        // 否则，根据indexs向量逐级查找子菜单
        QMenu* currentMenu = nullptr;
        bool pathBroken = false;
        
        for (int i = 0; i < indexs.size(); ++i) {
            int index = indexs.at(i);
            
            if (i == 0) {
                // 第一层，从菜单栏查找
                if (index >= 0 && index < menuBar->actions().size()) {
                    QAction* menuAction = menuBar->actions().at(index);
                    if (menuAction->menu())
                    {
                        currentMenu = menuAction->menu();
                    }
                    else
                    {
                        // 如果该位置没有子菜单，创建一个
                        currentMenu = new QMenu(menuAction->text(), menuBar);
                        menuAction->setMenu(currentMenu);
                    }
                } else {
                    // 索引无效，路径中断
                    pathBroken = true;
                    break;
                }
            } else {
                // 非第一层，从currentMenu中查找
                if (currentMenu && index >= 0 && index < currentMenu->actions().size())
                {
                    QAction* subMenuAction = currentMenu->actions().at(index);
                    if (subMenuAction->menu())
                    {
                        currentMenu = subMenuAction->menu();
                    }
                    else
                    {
                        // 如果该位置没有子菜单，创建一个
                        currentMenu = new QMenu(subMenuAction->text(), menuBar);
                        subMenuAction->setMenu(currentMenu);
                    }
                }
                else
                {
                    // 索引无效，路径中断
                    pathBroken = true;
                    break;
                }
            }
        }
        
        // 根据路径匹配情况添加菜单项
        if (pathBroken) {
            // 如果路径在某个点中断，将菜单项添加到最后匹配到的菜单位置
            if (currentMenu) {
                // 如果至少部分路径有效，添加到当前匹配到的菜单
                currentMenu->addAction(action=new QAction(title,currentMenu));
            } else {
                // 如果完全没有匹配到路径，添加到菜单栏
                menuBar->addAction(action=new QAction(title,menuBar));
            }
        } else if (currentMenu) {
            // 路径完全有效，将action添加到最终匹配的菜单中
            currentMenu->addAction(action=new QAction(title,currentMenu));
        } else {
            // 默认添加到菜单栏
            menuBar->addAction(action=new QAction(title,menuBar));
        }
    }
    // 如果提供了pActionWidget，则连接信号槽以显示对话框
    if (pActionWidget) {
        pActionWidget->setParent(this);
        connect(action, &QAction::triggered, this, [pActionWidget]()
        {
            pActionWidget->exec();
        });
    }
}

/**
 * @brief 注册菜单项到主窗口（重载3）
 * @param menuIndex 菜单索引，表示菜单项的位置
 * @param title 菜单名字
 * @return 菜单对象
 */
QMenu *DockWidgetManager::onRegisterMenuItem(int menuIndex, const QString &title)
{
    QMenu* currentMenu=new QMenu(title,ui->menuBar);
    QList<QAction*>actions= ui->menuBar->actions();
    if(menuIndex<0||menuIndex>=actions.size())
    {
        ui->menuBar->addMenu(currentMenu);
    }
    else
    {
         ui->menuBar->insertMenu(actions.at(menuIndex),currentMenu);
    }

    return currentMenu;
}

/**
 * @brief 注册widget到图形显示区域
 * 
 * 将图形显示组件添加到MDI区域，并建立GUID到子窗口的映射。
 * 如果GUID已存在则忽略，否则创建新的QMdiSubWindow并设置窗口标题和信号槽连接。
 * 
 * @param graphicsGuid 图形窗口的唯一标识符
 * @param titleString 图形窗口的标题
 * @param pWidget 要显示的图形组件
 */
void DockWidgetManager::registerGraphicsDisplayWidget(const QString &graphicsGuid, const QString &titleString, QWidget *pWidget)
{
    if(m_GraphicsSubWindowMap.contains(graphicsGuid))
    {
        return;
    }
    QMdiSubWindow *subWindow = ui->mdiArea_ImageDisplay->addSubWindow(pWidget);
    m_GraphicsSubWindowMap[graphicsGuid] = subWindow;
    subWindow->setWindowTitle(titleString);
    // 连接子窗口的destroyed信号到槽函数
    connect(subWindow, &QMdiSubWindow::destroyed, this, [this, graphicsGuid]() {
        // 检查是否还在映射中，如果不在说明已经被处理过了
        if (m_GraphicsSubWindowMap.contains(graphicsGuid)) {
            m_GraphicsSubWindowMap.remove(graphicsGuid);
            emit graphicsDisplayWidgetClosed(graphicsGuid);
        }
    });
    m_currentSelectedGuid = graphicsGuid;
    pWidget->update();
    ui->mdiArea_ImageDisplay->update();
}

/**
 * @brief 注销图形显示窗口
 * 
 * 从MDI区域中移除指定GUID的图形显示窗口，并更新内部映射。
 * 从映射表中移除对应的条目，从MDI区域中移除子窗口，并释放子窗口资源。
 * 注意：此函数不会删除widget，widget的生命周期由插件管理器管理。
 * 
 * @param graphicsGuid 要注销的图形窗口标识符
 */
void DockWidgetManager::unregisterGraphicsDisplayWidget(const QString &graphicsGuid)
{
    if (m_GraphicsSubWindowMap.contains(graphicsGuid)) {
        QMdiSubWindow *subWindow = m_GraphicsSubWindowMap.take(graphicsGuid);
        if (subWindow) {
            // 获取imageDisplayDock
            QDockWidget *imageDisplayDock = getDockWidget(DockWidgetType::ImageDisplay);
            if (imageDisplayDock) {
                // 获取dockWidget_ImageDisplay中的布局
                QWidget *dockWidget = imageDisplayDock->widget();
                if (dockWidget) {
                    QLayout *layout = dockWidget->layout();
                    if (layout && layout->count() > 0) {
                        // 获取QMdiArea
                        QMdiArea *mdiArea = qobject_cast<QMdiArea*>(layout->itemAt(0)->widget());
                        if (mdiArea) {
                            // 从MDI区域中移除子窗口
                            mdiArea->removeSubWindow(subWindow);
                        }
                    }
                }
            }
            
            // 注意：这里不删除widget，让插件管理器管理widget的生命周期
            QWidget* widget = subWindow->widget();
            subWindow->setWidget(nullptr);
            widget->setParent(nullptr);
            // 删除子窗口对象
            delete subWindow;
            
            emit graphicsDisplayWidgetClosed(graphicsGuid);
        }
    }
}

/**
 * @brief 切换到指定的图形显示窗口
 * 
 * 激活并显示具有指定GUID的图形显示窗口。如果指定GUID的窗口已存在且与当前活动窗口不同，
 * 则将其设置为活动窗口并发出切换信号。
 * 
 * @param graphicsGuid 目标图形窗口的标识符
 */
void DockWidgetManager::switchToGraphicsDisplayWidget(const QString &graphicsGuid)
{
    if (m_currentSelectedGuid == graphicsGuid) {
        return;
    }
    if (m_GraphicsSubWindowMap.contains(graphicsGuid)) {
        QMdiSubWindow *subWindow = m_GraphicsSubWindowMap[graphicsGuid];
        if (!subWindow) {
            return;
        }
        
        // 获取imageDisplayDock
        QDockWidget *imageDisplayDock = getDockWidget(DockWidgetType::ImageDisplay);
        if (imageDisplayDock) {
            // 获取dockWidget_ImageDisplay中的布局
            QWidget *dockWidget = imageDisplayDock->widget();
            if (dockWidget) {
                QLayout *layout = dockWidget->layout();
                if (layout && layout->count() > 0) {
                    // 获取QMdiArea
                    QMdiArea *mdiArea = qobject_cast<QMdiArea*>(layout->itemAt(0)->widget());
                    if (mdiArea && mdiArea->activeSubWindow() != subWindow) {
                        m_currentSelectedGuid = graphicsGuid;
                        // 激活并显示指定的子窗口
                        subWindow->showMaximized();
                        subWindow->show();
                        subWindow->raise();
                        subWindow->activateWindow();
                        mdiArea->update();
                        
                        emit graphicsDisplayWidgetSwitched(graphicsGuid);
                    }
                }
            }
        }
    }
}

